﻿//
// Created by Scave on 2023/11/13.
//

#ifndef RIDER3D_SHADERPROGRAM_H
#define RIDER3D_SHADERPROGRAM_H

#include "Define.h"
#include "bgfx/bgfx.h"
#include "resource/Resource.h"

NS_RIDER_BEGIN

#define MAX_LIGHTS 8
    const static char* UNIFORM_CAMERA_POSITION = "u_cameraPos";
    const static char* UNIFORM_MATERIAL_PARAMS = "u_materialParams";
    const static char* UNIFORM_AMBIENT_COLOR = "u_ambientColor";
    const static char* UNIFORM_LIGHTS = "u_lights";
    const static char* UNIFORM_LIGHT_COUNT = "u_lightCount";
    const static char* TEXTURE_MAIN = "s_mainTexture";
    const static char* TEXTURE_SPECULAR = "s_specularTexture";

    /// 着色器程序抽象基础类
    class ShaderProgram {
    public:
        bgfx::VertexLayout vertex_layout_;
        bgfx::ProgramHandle program_handle_ = BGFX_INVALID_HANDLE;

        ShaderProgram();

        ~ShaderProgram();

        /// 从二进制数据中载入着色器程序
        /// \param vs_data 顶点着色器代码
        /// \param vs_data_len 顶点着色器代码长度
        /// \param fs_data 片元着色器代码
        /// \param fs_data_len 片元着色器代码长度
        void Load(const unsigned char* vs_data,
                  uint16_t vs_data_len,
                  const unsigned char* fs_data,
                  uint16_t fs_data_len);

        /// 从指定路径加载着色器程序
        /// \param res_path 着色器程序所处目录路径
        /// \param vs_name 顶点着色器文件名
        /// \param fs_name 片元着色器文件名
        void Load(const char* res_path, const char* vs_name, const char* fs_name);

        /// 向shader传递uniform vec4参数
        /// \param name 参数名
        /// \param data xyzw分量数组
        void SetUniformV4(const String& name, float data[4]);

        /// 向shader传递uniform vec4数组
        /// \param name 参数名
        /// \param data xyzw分量数组
        void SetUniformV4Array(const String& name, void* data, UInt16 num_array);

        /// 向shader传递uniform mat4参数
        /// \param name 参数名
        /// \param data 4维矩阵数组
        void SetUniformMat4(const String& name, float data[16]);

        /// 向shader传递纹理
        /// \param name 参数名
        /// \param texture 纹理
        void SetTexture(UInt8 stage, const String& name, Texture2D texture);

    protected:
        HASHMAP<String, bgfx::UniformHandle> uniform_handle_map_;
    };

    class MinimumShaderProgram : public ShaderProgram {
    public:
        MinimumShaderProgram();
    };

    class StandardShaderProgram : public ShaderProgram {
    public:
        StandardShaderProgram();
    };

    class InstancingShaderProgram : public ShaderProgram {
    public:
        InstancingShaderProgram();
    };

NS_RIDER_END

#endif //RIDER3D_SHADERPROGRAM_H
